home *** CD-ROM | disk | FTP | other *** search
- /* GRAPHIC LISP */
- /* Scritto nel 1991-94 da Zoia Andrea Michele */
- /* Via Pergola #1 Tirano (SO) Tel. 0342-704210 */
- /* file clos_lf7.c */
-
- #include "clos.h"
-
- #define PHASE_PARAM 0
- #define PHASE_OPTIONAL 1
- #define PHASE_REST 2
- #define PHASE_REST_1 3
- #define PHASE_REST_2 4
- #define PHASE_KEY 5
- #define PHASE_AUX 6
-
- node convert_to_parlist();
-
-
- void lf_lambda LF_PARAMS
- {
- /* controllare se non si usa mai EVAL */
- /* allora tutte le variabili possono essere static */
- int phase;
- node curr;
- node parlist;
- node l;
- node prec;
- node fun;
- node anonimous;
- node optional;
- node rest;
- node key;
- node aux;
-
- node n_n;
- node n_c;
-
- node u_type;
- node prec_u_type;
- node u_par;
- node u_opt;
- node u_rest;
- node u_aux;
- node u_key;
-
- /*(lambda(p1..pn &optional .... &rest name &key .... &aux .... )sx1 .. sxn)*/
- /* metasimbolo '....' significa [name | (name initialvalue)]* */
-
-
- /* userfunc.params =(p1 p2 .. pn) */
- /* userfunc.opt =((opt1 . val1)..) */
- /* userfunc.rest =restanme */
- /* userfunc.key =((key1 . val1)..) */
- /* userfunc.aux =((aux1 . val1)..) */
- /* userfunc.sexprs =(sx1 .. sxn) */
- /* userfunc.env =env */
- /* NB: i parametri normali possono anche essere: (parname classname) */
-
-
-
- phase=PHASE_PARAM;
- prec=NIL;
-
- if(!IS_CONS(nin))
- error(E_FEWARGS,ERR_TBLVL|ERR_MERROR|ERR_PNODE,&nin);
-
- /* si allocano questi nodi in modo da controllare */
- /* piu' velocemente il nome degli atomi */
- /* perche' se 2 nodi hanno lo stesso nome */
- /* hanno anche lo stesso handle */
- optional=node_alloc("OPTIONAL");
- rest=node_alloc("REST");
- key=node_alloc("KEY");
- aux=node_alloc("AUX");
-
-
- u_type=u_par=u_opt=u_rest=u_key=u_aux=NIL;
-
-
- l=parlist=list_dup(CONSLEFT(nin),DUP_LASTNIL);
- /* l=parameter-list (p1 p2 &optional....) */
- /* bisogna duplicarla perche' viene alterata */
- /* si scarta l'eventuale ultimo elemento se la lista */
- /* non finisce con NIL es: (2 3 . 4) --> (2 3) */
-
- /* si scandisce la lista l */
- while(IS_CONS(l)){
- curr=CONSLEFT(l);
- switch(phase){
- case PHASE_PARAM:
- if(IS_NAME(curr) && HAS_NAME(curr)){
- l=CONSRIGHT(prec=l); /* prossimo elemento */
- /* e cosi' via fintanto */
- /* che non si trova */
- /* un nodo & */
- if(u_type==NIL){
- u_type=prec_u_type=node_make();
- }else{
- CONSRIGHT(prec_u_type)=node_make();
- prec_u_type=CONSRIGHT(prec_u_type);
- }
- TYPE(prec_u_type)|=NT_IS_CONS;
- CONSLEFT(prec_u_type)=CONSRIGHT(prec_u_type)=NIL;
- break;
- }
- if(IS_CONS(curr)){
- /* si guarda se e' una lista (nome classe) */
- n_n=CONSLEFT(curr);
- if(IS_CONS(curr=CONSRIGHT(curr))){
- n_c=CONSLEFT(curr);
- if(IS_NAME(n_n)&&HAS_NAME(n_n)){
- if(IS_NAME(n_c)&&HAS_NAME(n_c)){
- if(HAS_CLASS(n_c)){
- CONSLEFT(l)=n_n;
- CONSRIGHT(curr)=NIL;
- if(u_type==NIL){
- u_type=prec_u_type=curr;
- }else{
- CONSRIGHT(prec_u_type)=curr;
- prec_u_type=curr;
- }
- l=CONSRIGHT(prec=l);
- break;
- }
- error(E_UNBOUNDCLASS,ERR_TBLVL|ERR_PNODE|ERR_MERROR,&n_c);
- }
- error(E_BADARGS,ERR_TBLVL|ERR_PNODE|ERR_MERROR,&n_c);
- }
- error(E_BADARGS,ERR_TBLVL|ERR_PNODE|ERR_MERROR,&n_n);
- }
- error(E_BADLIST,ERR_TBLVL|ERR_PNODE|ERR_MERROR,&CONSLEFT(l));
- }
- if(IS_VALUE(curr)&&(GET_VTYPE(curr)==NT_ENAME)){
- if(prec!=NIL){
- CONSRIGHT(prec)=NIL; /* si spezza parlist */
- u_par=parlist; /* e la si assegna a ufuncpar */
- }else{
- u_par=NIL;
- }
- if(ENAME(curr)!=optional)
- goto Optional_chk;
- parlist=l=CONSRIGHT(prec=l);
- phase=PHASE_OPTIONAL;
- break;
- }
- error(E_LAMBDASYNTAX,ERR_TBLVL|ERR_PNODE|ERR_MERROR,&CONSLEFT(nin));
-
- case PHASE_OPTIONAL:
- if(IS_VALUE(curr)&&(GET_VTYPE(curr)==NT_ENAME)){
- CONSRIGHT(prec)=NIL;
- /*l punta al prossimo cons */
- /* parlist contiene i parametri selezionati*/
- u_opt=convert_to_parlist(parlist);
-
- Optional_chk:
- if(ENAME(curr)!=rest)
- goto Rest_chk;
- parlist=l=CONSRIGHT(prec=l);
- phase=PHASE_REST_1;
- break;
- }
- l=CONSRIGHT(prec=l);
- break;
-
- case PHASE_REST_1:
- if(IS_NAME(curr)&&HAS_NAME(curr)){
- l=CONSRIGHT(prec=l);
- phase=PHASE_REST_2;
- break;
- }
- error(E_LAMBDASYNTAX,ERR_TBLVL|ERR_PNODE|ERR_MERROR,&CONSLEFT(nin));
-
- case PHASE_REST_2:
- if(IS_VALUE(curr)&&(GET_VTYPE(curr)==NT_ENAME)){
- u_rest=CONSLEFT(prec);
- Rest_chk:
- if(ENAME(curr)!=key)
- goto Key_chk;
- parlist=l=CONSRIGHT(prec=l);
- phase=PHASE_KEY;
- break;
- }
- error(E_LAMBDASYNTAX,ERR_TBLVL|ERR_PNODE|ERR_MERROR,&CONSLEFT(nin));
- case PHASE_KEY:
- if(IS_VALUE(curr)&&(GET_VTYPE(curr)==NT_ENAME)){
- CONSRIGHT(prec)=NIL;
- u_key=convert_to_parlist(parlist);
- Key_chk:
- if(ENAME(curr)!=aux)
- error(E_LAMBDASYNTAX,ERR_TBLVL|ERR_PNODE|ERR_MERROR,&CONSLEFT(nin));
- parlist=l=CONSRIGHT(prec=l);
- phase=PHASE_AUX;
- break;
- }
- l=CONSRIGHT(prec=l);
- break;
- case PHASE_AUX:
- if(IS_VALUE(curr)&&(GET_VTYPE(curr)==NT_ENAME))
- error(E_LAMBDASYNTAX,ERR_TBLVL|ERR_PNODE|ERR_MERROR,&CONSLEFT(nin));
- l=CONSRIGHT(l);
- break;
- }
- }
- switch(phase){
- case PHASE_PARAM:
- u_par=parlist;
- break;
- case PHASE_OPTIONAL:
- u_opt=convert_to_parlist(parlist);
- break;
- case PHASE_REST_1:
- break;
- case PHASE_REST_2:
- u_rest=CONSLEFT(parlist);
- break;
- case PHASE_KEY:
- u_key=convert_to_parlist(parlist);
- break;
- case PHASE_AUX:
- u_aux=convert_to_parlist(parlist);
- break;
- }
-
- l=CONSRIGHT(nin); /* l=sexprs-list*/
-
- if(IS_CONS(l)){
-
- fun=node_make();
- anonimous=node_make();
-
- FUNCTION(anonimous)=fun;
- TYPE(fun)|=NT_IS_VALUE+NT_UFUNC;
- TYPE(anonimous)|=NT_IS_NAME+NT_HAS_FUNCTION+NT_HAS_VALUE;
- VALUE(anonimous)=anonimous;
-
- UFUNC_TYPE(fun)=u_type;
- UFUNC_SEX(fun)=l;
-
- /* lenv e' una lista di a-list */
- /* lenv-modifica */
- UFUNC_ENV(fun)=lenv;
- UFUNC_PAR(fun)=u_par;
- UFUNC_OPT(fun)=u_opt;
- UFUNC_AUX(fun)=u_aux;
- UFUNC_REST(fun)=u_rest;
- UFUNC_KEY(fun)=u_key;
-
- nout->type=P_VALUE;
- nout->node=anonimous;
- return;
- }
- error((l==NIL)?E_SLAMBDA:E_BADLIST,ERR_TBLVL|ERR_PNODE|ERR_MERROR,&nin);
- }
-
-
-
-
- node convert_to_parlist( l)
- node l;
- {
- /* prende in ingresso una lista ( A1 A2 ... An ) */
- /* dove Ai e' [ Ni | (Ni Vi) ] {nome oppure lista con nome e valore} */
- /* e genera una A-LIST ( (N1 . V1) (N2 . V2) ... (Nn . Vn) ) */
- /* dove Ni=NIL se Ai=Ni Ni=Vi se Ai=(Ni Vi) */
- /* se la lista d'ingresso ha qualche errore lo si segnala e si ritorna */
- /* alla riga di comando */
-
- node alist;
- node prev;
- node n;
- node lin;
- node name;
- node value;
-
-
- alist=NIL;
- lin=l;
- prev=NIL;
-
- while(l!=NIL){
- /* si scandisce l */
-
- if(IS_CONS(l)){
- n=CONSLEFT(l);
- if(IS_CONS(n)){/* caso n=(Ni Vi) */
- value=CONSRIGHT(n);
- name=CONSLEFT(n);
- if(IS_CONS(value)){
- if(CONSRIGHT(value)==NIL){
- value=CONSLEFT(value);
- }else{
- error(E_LAMBDASYNTAX,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&lin);
- }
- }else{
- error(E_LAMBDASYNTAX,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&lin);
- }
- }else{ /* caso n=Ni */
- name=n;
- value=NIL;
- }
- /* si inserisce (name.value) in fondo ad alist */
- n=node_make();
- TYPE(n)|=NT_IS_CONS;
- CONSLEFT(n)=name;
- CONSRIGHT(n)=value;
- name=node_make();
- TYPE(name)|=NT_IS_CONS;
- CONSLEFT(name)=n;
- CONSRIGHT(name)=NIL;
- if(alist==NIL){
- alist=prev=name;
- }else{
- CONSRIGHT(prev)=name;
- prev=name;
- }
- }else{
- error(E_LAMBDASYNTAX,ERR_MERROR|ERR_PNODE|ERR_TBLVL,&lin);
- }
- l=CONSRIGHT(l); /* prossimo elemento */
- }
- return alist;
- }
-
-
-
-
-
-
-
-
-